package com.card.game;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import com.card.common.CardContants;
import com.card.common.MessageComm;
import com.card.game.room.AbstractRoom;
import com.card.game.room.SHRoom;
import com.card.main.GameConfig;
import com.card.message.JsonMessageCenter;
import com.card.user.User;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.xiaoao.net.global.Global;
import com.xiaoao.net.json.message.JsonMessage;

public class Player extends BasePlayer{
	private Card lastInCard;
	private transient Hand hand = new Hand();
	private int handSize;
	protected Vector<Card> outCards = new Vector<>();
	public boolean ting;
	
	protected List<Card> tingCardList = Lists.newArrayList();
	
	protected List<Card> gangList = Lists.newArrayList();
	protected List<Card> anGangList = Lists.newArrayList();
//	protected List<CardHeap> jiaGangList = Lists.newArrayList();
	private transient Map<Card,String> duiCards = Maps.newConcurrentMap();
	protected List<Card> duiList = Lists.newArrayList();
	
	protected List<Card> noGangCard = Lists.newArrayList();
	protected List<CardHeap> chiList = Lists.newArrayList();
	protected List<Card> huaPaiList = Lists.newArrayList();
	
//	private transient PlayerSkill playerSkill;
	private transient List<Card> isNoGuoGang = Lists.newArrayList();
	public int jiaBei = 0;//本局加倍数    新加！！！
	public boolean isCanJiaBei = true; //新加！！！本局是否已经加过了
	public int kouNum;//显示形成口数
	public transient Multiset<String> baoPaiMap = HashMultiset.create();
	private transient List<Card> showTingCards = Lists.newArrayList();
	private transient boolean onlyZimo;
	private transient boolean isNoCanHu;
	public transient boolean isTianHu = true;
	public int pao = 1; //gp加！下跑,一个跑加一底分
	
	public Player(User user) {
		super(user);
	}
	public void initCards(Vector<Card> cards) {
		this.hand.cards = cards;
		this.handSize = this.hand.cards.size();
		sortCard();
	}
	
	public void addCard(Card card) {
		this.hand.cards.add(card);
		this.lastInCard = card;
		this.handSize = this.hand.cards.size();
		sortCard();
	}
	public void addNoHuCard(Card card) {
		if(GameConfig.guoHu) {
			this.isNoCanHu = true;
		}
	}
	public void clearNoHuCard() {
		this.isNoCanHu = false;
	}
	
	public boolean removeCard(Card card) {
		boolean suc =  this.hand.cards.remove(card);
		this.handSize = this.hand.cards.size();
		return suc;
	}
	public void removeOutCard(Card card) {
		this.outCards.remove(card);
	}
	public void removeLastOutCard(Card card) {
		for (int i = outCards.size()-1; i >= 0; i--) {
			if(outCards.get(i).equals(card)) {
				outCards.remove(i);
				return ;
			}
		}
		outCards.remove(outCards.size()-1);
	}
	
	public Card getLastInCard() {
		if(lastInCard == null) {
			return hand.firstElement();
		}
		return lastInCard;
	}
	public void setLastInCard(Card lastInCard) {
		this.lastInCard = lastInCard;
	}
	public Card removeFirst() {
		Card card = this.hand.cards.remove(0);
		this.handSize = this.hand.cards.size();
		return card;
	}
	public Hand getHand() {
		return hand;
	}
	public List<Card> getAllGangList() {
		List<Card> ccs = Lists.newArrayList();
		ccs.addAll(gangList);
		ccs.addAll(anGangList);
		return ccs;
	}
//	public List<Card> getGangCardsList() {
//		return gangList;
//	}
	public List<Card> getAnGangList() {
		return anGangList;
	}
	public List<Card> getMingGangList() {
		return gangList;
	}
	public List<Card> getDuiCardsList() {
		return duiList;
	}
	public Map<Card, String> getDuiCards() {
		return duiCards;
	}
	public String removeDuiCard(Card duiCard) {
		duiList.remove(duiCard);
		return duiCards.remove(duiCard);
	}
	
	public void clear() {
		super.clear();
		this.hand.clear();
		this.outCards.clear();
	}
	
	public Card handOut(Card card,boolean isTing) {
		boolean isExit = removeCard(card);
		if(!isExit) {
			card = removeFirst();
		}
		this.isNoGuoGang.clear();
		if(outCards.isEmpty()) {
			playerInfo.setFirstOut(card);
		}
		SHRoom room = (SHRoom)user.getRoom();
		if(room.isHZRoom() || !card.isHuaCard()){
			outCards.add(card);
		}
		return card;
	}
	
	
	public Vector<Card> getOutCards() {
		return outCards;
	}
	
	public boolean isCanMingGang(Card outCard) {
		boolean isCanGang = hand.isCanMingGang(outCard);
		if(isCanGang && ting) {
			Vector<Card> cloneCards = (Vector<Card>)hand.cards.clone();
			for (int i = 0; i < 3; i++) {
				cloneCards.remove(outCard);
			}
			List<Card> tempList = getTingCards(cloneCards);
			isCanGang = KdUtils.isCanTing(tempList,tingCardList);
		}
		return isCanGang;
	}
	
	public PlayerEvent getHandOutEvent(SHRoom room,Card outCard,int curIndex,Player player) {
		boolean isCanHu = false;
		if(!room.isHZRoom()) {
//			System.out.println("Player:182");
			isCanHu = isCanHu(outCard);
		}
		boolean isCanGang = isCanMingGang(outCard);
		boolean isCanDui = isCanGang || hand.isCanDui(outCard);
		if(outCard.isOutJin()) {
			isCanGang=false;isCanDui=false;
		}
		if(ting) isCanDui = false;
		List<Card> gangList = Lists.newArrayList();
		if(isCanGang) gangList.add(outCard);
		List<CardHeap> chiList = room.getCanChiList(this);
		
		if(isCanHu || isCanDui || !gangList.isEmpty() || chiList != null) {
			PlayerEvent event = new PlayerEvent(userId,curIndex,this.tableIndex, isCanHu, false, isCanDui,chiList);
			event.setGangList(gangList);
			return event;
		}
		return null;
	}
	
	public boolean checkQiangGang(SHRoom room,Card outCard,Player player) {
		if(room.isHZRoom()) {
			Card jinCard = room.getJinPai();
			if(outCard.equals(jinCard) || player.haveJin(jinCard)) {
				return false;
			}
		}
		boolean isQiangGang = isCanHu(outCard);
		if(isQiangGang) {
			PlayerEvent event = new PlayerEvent(userId,this.tableIndex,this.tableIndex, isQiangGang);
			room.setEvent(event);
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_PlayerEvent);
			message.addProperty("event", event);
			JsonMessageCenter.getInstance().sendMessage(message, event.getUserId());
			return true;
		}
		return false;
	}
	
	public boolean checkHandIn() {
		return checkHandIn(true);
	}
	
	public boolean checkHandIn(boolean isCanHu) {
//		System.out.println("checkHandIn");
		boolean isSanJin = false;
		boolean isZimo = isCanHu && isZimo();
		List<Card> outTingCards = Lists.newArrayList();
		if(GameConfig.isTing) 
		outTingCards = ting?new ArrayList<Card>():getOutCard2Ting();
		
		//判断过路杠
		List<Card> gangList = getListGuoGang();
		gangList.addAll(getListAnGang());
		
		if(isZimo || !outTingCards.isEmpty() || !gangList.isEmpty()) {
			PlayerEvent event = new PlayerEvent(userId,this.tableIndex,this.tableIndex, false, false,false);
			event.setZimo(isZimo);
			event.setSanJin(isSanJin);
			event.setOutTingCards(outTingCards);
			event.setGangList(gangList);
			user.getRoom().setEvent(event);
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_PlayerEvent);
			message.addProperty("event", event);
			JsonMessageCenter.getInstance().sendMessage(message, event.getUserId());
			return true;
		}
		if(ting && !isZimo) {
			user.getRoom().handOut(userId, this.lastInCard, false);
		}
		return false;
	}
	
	
	public void pengCard(Card outCard,String userId) {
//		if(isCanMingGang(outCard)) {
//			noGangCard.add(outCard);
//		}
		for (int i = 0; i < 2; i++) {
			removeCard(outCard);
		}
		Card gangCard = new Card(outCard.getType(), outCard.getIndex());
		gangCard.setHurtId(userId);
		duiCards.put(gangCard, userId);
		duiList.add(gangCard);
		addBaoPai(userId);
//		this.isNoGuoGang.add(outCard);
	}
	public void mingGangCard(Card outCard,String userId) {
		for (int i = 0; i < 3; i++) {
			removeCard(outCard);
		}
		Card gangCard = new Card(outCard.getType(), outCard.getIndex());
		gangList.add(gangCard);
		gangCard.setHurtId(userId);
		playerInfo.setLastGangId(userId);
		if(ting) {
			this.tingCardList = getTingCards(hand.cards);
		}
		
	}
	
	public void addBaoPai(String userId) {
		this.baoPaiMap.add(userId);
		if(isBaoPai(userId)) {
			this.onlyZimo = true;
			this.kouNum = this.baoPaiMap.count(userId);
			SHRoom room = (SHRoom)user.getRoom();
			Player tarPlayer = room.getPlayerById(userId);
			tarPlayer.onlyZimo = true;
		}
	}
	
	public void anGangCard(Card outCard) {
		for (int i = 0; i < 4; i++) {
			removeCard(outCard);
		}
		anGangList.add(outCard);
		if(ting) {
			this.tingCardList = getTingCards(hand.cards);
		}
	}
	
	public int getHandSize() {
		return hand.cards.size();
	}
	public void endGame() {
		super.endGame();
		this.lastInCard = null;
		this.ting = false;
		this.onlyZimo = false;
		this.isNoCanHu = false;
		this.isTianHu = true;
		this.kouNum = 0;
		this.hand.clear();
		this.outCards.clear();
		this.handSize = 0;
		this.gangList.clear();
//		this.jiaGangList.clear();
		this.tingCardList.clear();
		this.anGangList.clear();
		this.duiCards.clear();
		this.duiList.clear();
		this.playerInfo.endGame();
		this.noGangCard.clear();
		this.isNoGuoGang.clear();
		this.chiList.clear();
		this.huaPaiList.clear();
		this.showTingCards.clear();
		this.baoPaiMap.clear();
	}
	
	public String getLastGangId() {
		return playerInfo.getLastGangId();
	}
	
	private void checkTingCard() {
		for (Card card : this.tingCardList) {
			if(card.getIndex()>=CardContants.Min_Index || card.getType()>=CardType.DONG) {
				return;
			}
		}
		this.tingCardList.clear();
	}
	public boolean tingCard() {
//		System.out.println("tingCard");
		this.tingCardList = getTingCards(hand.cards);
		checkTingCard();
		this.ting = !this.tingCardList.isEmpty();
		return this.ting;
	}
	
	private boolean haveHua() {
		if(this.huaPaiList.size()>0) {
			return true;
		}
		if(gangList.size()>0 || anGangList.size()>0 || getPengSize()>0) {
			return true;
		}
		return false;
	}
	
	public boolean isCanHu(Card outCard) {
		SHRoom room = (SHRoom)user.getRoom();
		//gpgp
		if(GameConfig.isOnlyZimo || onlyZimo||!room.getRoomSetting().isCanDianpaoHu() || isNoCanHu) {
			return false;
		}
		if(GameConfig.isTing) {
			return ting && outCard.isDianpaoCard() 
					&& tingCardList.contains(outCard);
		}else{
//			if(!haveHua() || handHaveHua()) {
//				return false;
//			}
			if(room.haveJin()) {
				Vector<Card> copyCards = (Vector<Card>)hand.cards.clone();
				copyCards.add(outCard);
				return QzUtils.isZimo(copyCards,room.getRoomSetting().hasFeng());
			}else{
				if(GameConfig.ShowTing) {
					if(this.showTingCards.contains(outCard)) {
						if(AqUtils.is13Lan(hand.cards, outCard)) {
							return false;
						}
						return true;
					}
				}
				return false;
			}
		}
	}
	public boolean isTingCard(Card card) {
		return this.tingCardList.contains(card);
	}
	//gp获取ting牌值
	public List<Card> getTingCards(Vector<Card> cards) {
		SHRoom room = (SHRoom)user.getRoom();
		return KdUtils.getTingCards(cards,room.hunZi);
	}
	public boolean handHaveHua() {
		return AqUtils.haveHua(hand.cards);
	}
	
	public boolean isZimo() {
		if(GameConfig.isTing) {
			return ting
					&& tingCardList.contains(lastInCard);
		}else{
			SHRoom room = (SHRoom)user.getRoom();
			if(room.haveJin()) {
				return QzUtils.isZimo(hand.cards,room.getRoomSetting().hasFeng());
			}
			if(AqUtils.is13Lan(hand.cards)) {
				return true;
			}
			if(handHaveHua()) {
				return false;
			}
			if(GameConfig.ShowTing) {
				if(this.outCards.isEmpty()) {
					return AqUtils.isZimo(hand.cards,lastInCard);
				}
				return this.showTingCards.contains(lastInCard);
			}
			return AqUtils.isZimo(hand.cards,lastInCard);
		}
	}
	public List<Card> getListGuoGang() {
		List<Card> gangList = Lists.newArrayList();
		if(!ting) {
			for (Card card : duiCards.keySet()) {
				if(hand.cards.contains(card) && !noGangCard.contains(card)
						&& !isNoGuoGang.contains(card)) {
					gangList.add(card);
				}
			}
		}else{
			if(this.lastInCard != null && duiCards.containsKey(lastInCard)
					&& !noGangCard.contains(this.lastInCard)
					&& !isNoGuoGang.contains(this.lastInCard)) {
				gangList.add(this.lastInCard);
			}
		}
		
		return gangList;
	}
	
	public Card getGuoGang() {
		if(this.lastInCard != null && duiCards.containsKey(lastInCard)) {
			return lastInCard;
		}
		if(!ting) {
			for (Card card : duiCards.keySet()) {
				if(hand.cards.contains(card)) {
					return card;
				}
			}
		}
		return null;
	}
	
	public List<Card> getGuoLuGangList() {
		List<Card> cc = Lists.newArrayList();
		if(ting) {
			if(this.lastInCard != null && duiCards.containsKey(lastInCard)
					&& !noGangCard.contains(this.lastInCard)) {
				cc.add(lastInCard);
			}
		}else{
			for (Card card : duiCards.keySet()) {
				if(hand.cards.contains(card) && !noGangCard.contains(card)) {
					cc.add(card);
				}
			}
		}
		return cc;
	}
	
	public List<Card> getListAnGang() {
		List<Card> ads = HandUtils.getAnGang(hand.cards);
		if(ads.isEmpty()) return ads;
		
		for (int i = ads.size()-1; i >= 0; i--) {
			Card gangCard = ads.get(i);
			if(ting) {
				Vector<Card> cloneCards = (Vector<Card>)hand.cards.clone();
				for (int j = 0; j < 4; j++) {
					cloneCards.remove(gangCard);
				}
				List<Card> tempList = getTingCards(cloneCards);
				if(!KdUtils.isCanTing(tempList,tingCardList)) {
					ads.remove(i);
				}
			}
		}
		return ads;
	}
	
	public List<Card> getCheckGangList() {
		List<Card> gangList = HandUtils.getAnGang(hand.cards);
		if(ting) {
			for (int i = gangList.size()-1; i >= 0; i--) {
				Card gangCard = gangList.get(i);
				Vector<Card> cloneCards = (Vector<Card>)hand.cards.clone();
				for (int j = 0; j < 4; j++) {
					cloneCards.remove(gangCard);
				}
				List<Card> tempList = getTingCards(cloneCards);
				if(!KdUtils.isCanTing(tempList,tingCardList)) {
					gangList.remove(i);
				}
			}
		}
		gangList.addAll(getGuoLuGangList());
		return gangList;
	}
	public Card getAnGang() {
		List<Card> ads = HandUtils.getAnGang(hand.cards);
		if(ads.isEmpty()) return null;
		Card gangCard = ads.get(0);
		if(lastInCard != null && ads.contains(lastInCard)) {
			gangCard = lastInCard;
		}
		if(ting) {
			Vector<Card> cloneCards = (Vector<Card>)hand.cards.clone();
			for (int i = 0; i < 4; i++) {
				cloneCards.remove(gangCard);
			}
			List<Card> tempList = getTingCards(cloneCards);
			if(KdUtils.isCanTing(tempList,tingCardList)) {
				return gangCard;
			}
			return null;
		}
		return gangCard;
	}
	public void chiCard(Card outCard,List<Card> chiCards,String userId) {
		for (Card card : chiCards) {
			if(!card.equals(outCard)) {
				removeCard(card);
			}
		}
		chiList.add(new CardHeap(chiCards));
		addBaoPai(userId);
	}
	public List<CardHeap> getChiList() {
		return chiList;
	}
	
	public List<Card> getHuaPaiList() {
		return huaPaiList;
	}
	public boolean isQingyise() {
		Vector<Card> sour = (Vector<Card>)hand.cards.clone();
		sour.addAll(gangList);
		sour.addAll(anGangList);
		sour.addAll(duiList);
		return KdUtils.isQingyise(sour);
	}
	
	public List<Card> getShowTingCards() {
		return showTingCards;
	}
	public void setShowTingCards(List<Card> showTingCards) {
		this.showTingCards = showTingCards;
	}
	public List<Card> getOutCard2Ting() {
		return KdUtils.getOutCardForTing(hand.cards);
	}
	public void addHuaPai(Card card) {
		this.huaPaiList.add(card);
	}
	
	public int getJinPaiSize() {
		SHRoom room = (SHRoom)user.getRoom();
		Card jinPai = room.getJinPai();
		int num = 0;
		for (Card card : hand.cards) {
			if(card.equals(jinPai)) {
				num ++;
			}
		}
		return num;
	}
	public boolean isJinpaiHu() {
		SHRoom room = (SHRoom)user.getRoom();
		Vector<Card> cards = (Vector<Card>)getHand().cards.clone();
		List<Card> jinCards = QzUtils.getSameCard(cards, room.getJinPai());
		return jinCards.size() >= GameConfig.JinHuNum;
	}
	public void sortCard() {
		SHRoom room = (SHRoom)user.getRoom();
		if(room != null && room.haveJin()) {
			sortJin();
		}else{
			sortHua();
		}
	}
	private void sortJin() {
		SHRoom room = (SHRoom)user.getRoom();
		Card jinCard = room.getJinPai();
		List<Card> jins = QzUtils.getSameCard(this.hand.cards, jinCard);
		for (Card card : jins) {
			this.hand.cards.remove(card);
		}
		Collections.sort(this.hand.cards);
		for (Card card : jins) {
			this.hand.cards.add(0,card);
		}
	}
	private void sortHua() {
		List<Card> huaCard = Lists.newArrayList();
		for (int i = this.hand.cards.size()-1; i >= 0; i--) {
			Card c = this.hand.cards.get(i);
			if(c.isHuaCard()) {
				this.hand.cards.remove(i);
				huaCard.add(c);
			}
		}
		Collections.sort(this.hand.cards);
		if(!huaCard.isEmpty()) {
			Collections.sort(huaCard);
			this.hand.cards.addAll(huaCard);
		}
	}
	public void jiaBei(int bei) {
		this.jiaBei = bei;
		this.isCanJiaBei = false;
	}
	public int getJiaBei() {
		return jiaBei;
	}
	
	public boolean isTianHu() {
		return this.isTianHu;
	}
	public boolean isWuHua() {
		return this.huaPaiList.isEmpty();
	}
	public int getHuaSize() {
		return this.huaPaiList.size();
	}
	public int getPengSize() {
		int num = 0;
		for (Card card : this.duiList) {
			if(card.getType() >= CardType.DONG) {
				num ++;
			}
		}
		Vector<Card> clones = (Vector<Card>)this.hand.cards.clone();
		Collections.sort(clones);
		List<Hand> hands = CardUtils.findSameCardBySize(clones, 3);
		for (Hand hand : hands) {
			Card c = hand.cards.get(0);
			if(!c.isHuaCard() && c.getType() >= CardType.DONG) {
				num ++;
			}
		}
		return num;
	}
	public boolean isBaoPai(String userId) {
		return this.baoPaiMap.count(userId)>=3;
	}
	public boolean haveJin(Card jinCard) {
		for (Card card : hand.cards) {
			if(card.equals(jinCard)) {
				return true;
			}
		}
		return false;
	}
	
	public boolean isMenQing() {
//		if(!this.chiList.isEmpty() || !this.duiList.isEmpty()) {
//			return 0;
//		}
//		Vector<Card> clones = (Vector<Card>)cards.clone();
//		clones.add(huCard);
//		for (Card c : this.gangList) {
//			clones.add(c);
//		}
//		return AqUtils.getMenQing(clones);
		
		return this.chiList.isEmpty() && this.duiList.isEmpty() && this.gangList.isEmpty();
	}
	
	public boolean isHZMenQing() {
		return this.duiList.isEmpty() && this.gangList.isEmpty();
	}
}
